import requests
import time
import sys
import threading

import signal
import configparser
import datetime

from queue import Queue
from optparse import OptionParser


class Worker(threading.Thread):
    """
    Multi-threaded acquisition
    """
    def __init__(self, work_queue, result_queue):

        threading.Thread.__init__(self)

        self.work_queue = work_queue
        self.result_queue = result_queue
        signal.signal(signal.SIGINT, quit)
        signal.signal(signal.SIGTERM, quit)

        self.setDaemon(True)
        self.start()

    def quit(self):
        sys.exit()

    def run(self):
        while True:
            func, arg, code_index = self.work_queue.get()
            res = func(arg, code_index)
            self.result_queue.put(res)
            if self.result_queue.full():
                res = sorted([self.result_queue.get() for i in range(self.result_queue.qsize())], key=lambda s: s[0], reverse=True)
                # res.insert(0, ('0', u'名称     股价'))
                ts = datetime.datetime.now().strftime('%Y.%m.%d-%H:%M:%S')
                print ('\n***** ' + ts +' *****')
                for obj in res:
                    print (obj[1])
                # print ('***** end *****\n')
            self.work_queue.task_done()


class Stock(object):

    """
    Real-time stock price acquisition
    """

    def __init__(self, code, thread_num):
        self.code = code
        self.work_queue = Queue()
        self.threads = []
        self.__init_thread_poll(thread_num)

    def __init_thread_poll(self, thread_num):
        self.params = self.code.split(',')
        # self.params.extend(['s_sh000001', 's_sz399001'])  # 默认获取沪指、深指
        self.result_queue = Queue(maxsize=len(self.params[::-1]))
        for i in range(thread_num):
            self.threads.append(Worker(self.work_queue, self.result_queue))

    def __add_work(self, stock_code, code_index):
        self.work_queue.put((self.value_get, stock_code, code_index))

    def del_params(self):
        for obj in self.params:
            self.__add_work(obj, self.params.index(obj))

    def wait_all_complete(self):
        for thread in self.threads:
            if thread.isAlive():
                thread.join()

    @classmethod
    def value_get(cls, code, code_index):
        # 名称, 昨日收盘价, 当前价, 涨幅
        slice_num, zs_num, value_num = 21, 2, 3
        name, zrspj, now = u'——无——', u'  ——无——', u'  ——无——'
        increase = 0.00
        field_len = 10

        # if code in ['s_sh000001', 's_sz399001']:
        #     slice_num = 23
        #     value_num = 1
        r = requests.get("http://hq.sinajs.cn/list=%s" % (code,))
        res = r.text.split(',')
        if len(res) > 1:
            name, zrspj, now = r.text.split(',')[0][slice_num:],  r.text.split(',')[zs_num], r.text.split(',')[value_num]

            increase = (float(now) - float(zrspj))/float(zrspj)*100
            # 名称+代码
            name = name[0:1] + code[2:]
            name = name.ljust(8, ' ')
            zrspj = zrspj.ljust(field_len, ' ')
            now = now.ljust(field_len, ' ')

        return code_index, name + ' ' + zrspj + ' ' + now + ' ' + str('{:.2f}%'.format(increase))


if __name__ == '__main__':
    # 读取配置文件中的股票代码
    config = configparser.ConfigParser()
    config.read('config.ini')
    codes = config['stock']['codes']

    parser = OptionParser(description="Query the stock's value.", usage="%prog [-c] [-s] [-t]", version="%prog 1.0")
    parser.add_option('-c', '--stock-code', dest='codes', default=codes,
                      help="the stock's code that you want to query.")

    parser.add_option('-s', '--sleep-time', dest='sleep_time', default=6, type="int",
                      help='How long does it take to check one more time.')

    parser.add_option('-t', '--thread-num', dest='thread_num', default=3, type='int',
                      help="thread num.")

    options, args = parser.parse_args(args=sys.argv[1:])

    assert options.codes, "Please enter the stock code!"  # 是否输入股票代码

    if list(filter(lambda s: s[:-6] not in ('sh', 'sz', 's_sh', 's_sz'), options.codes.split(','))):  # 股票代码输入是否正确
        raise ValueError

    stock = Stock(options.codes, options.thread_num)

    try:
        while True:
            stock.del_params()
            time.sleep(options.sleep_time)
    except Exception as exc:
        pass